package cn.wangkai.peanut.db.manager;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.wangkai.peanut.db.DbFactory;
import cn.wangkai.peanut.db.WKDbException;
import cn.wangkai.peanut.db.iface.IDbFactory;
import cn.wangkai.peanut.db.iface.IMyDb;
import cn.wangkai.peanut.db.mod.GeneratedKey;
import cn.wangkai.peanut.db.mod.ModelUtil;
import cn.wangkai.peanut.db.util.ManagerException;
import cn.wangkai.peanut.db.util.PageModel;
import cn.wangkai.peanut.db.util.SQLUtil;
import cn.wangkai.peanut.system.dao.sequence.SequenceManager;
import cn.wangkai.peanut.system.dao.sequence.SequenceManagerImp;



public class ManagerImp<T> implements Manager<T> {
	
	private Log log = LogFactory.getLog(ManagerImp.class);
	private IDbFactory dbFactory = new DbFactory();
	private SequenceManager sequenceManager = new SequenceManagerImp();
	private T module= null;
	public String[] keywords = ModelUtil.getClassPrimaryKeys(getModuleClass());
	public String Tablename = ModelUtil.getClassName(getModuleClass());
	public ManagerImp() {
	}

	public Log getLog() {
		return log;
	}

	public void setLog(Log log) {
		this.log = log;
	}

	public IDbFactory getDbFactory() {
		return dbFactory;
	}


	public void setDbFactory(IDbFactory dbFactory) {
		this.dbFactory = dbFactory;
	}


	public SequenceManager getSequenceManager() {
		return sequenceManager;
	}


	public void setSequenceManager(SequenceManager sequenceManager) {
		this.sequenceManager = sequenceManager;
	}


	public T getModule() {
		return module;
	}

	public Class<?> getModuleClass() {
		return module.getClass();
	}
	

	public void setModule(T module) {
		this.module = module;
	}


	@Override
	public T add(IMyDb db, T t) throws SQLException, WKDbException, ManagerException, WKDbException {
		log.debug("add "+t.getClass().getName());
		if(ModelUtil.getClassKeywordAuto(t.getClass())){
			GeneratedKey getkey = dbFactory.addselectgetID(db, t);
			return findById(db, getkey.getGeneratedKey());
		}else{
			Object[] keysval = new Object[keywords.length];
			for (int i = 0; i < keywords.length; i++) {
				String keyword = keywords[i];
				Method key = ModelUtil.getClassMethod(t, keyword);
				keysval[i] = getObjKey(key,t);
				if(keysval[i]==null) {
					if(keywords.length==1) {
						keysval[i] = sequenceNext(key, t);
					} else {
						throw new WKDbException("keywords is null ");
					}
				}
			}
			dbFactory.addselectgetID(db, t);
			return findById(db, keysval);
		}
		
	}

	/**
	 * 自动填充主键ID
	 * @param key
	 * @param t
	 * @return
	 */
	private Object sequenceNext(Method key,T t) {
		try {
			Map<String,Object> maps = new HashMap<String,Object>();
			if (key.getReturnType().isAssignableFrom(java.lang.Long.class)) {
				maps.put(keywords[0], sequenceManager.getNextLongSequence(Tablename+"_"+keywords[0]));
			}else if (key.getReturnType().isAssignableFrom(String.class)) {
				maps.put(keywords[0], sequenceManager.getNextSequence(Tablename+"_"+keywords[0]));
			}else if (key.getReturnType().isAssignableFrom(Integer.class)) {
				maps.put(keywords[0], sequenceManager.getNextIntSequence(Tablename+"_"+keywords[0]));
			}else if (key.getReturnType().isAssignableFrom(BigDecimal.class) ) {
				maps.put(keywords[0], new BigDecimal(sequenceManager.getNextLongSequence(Tablename+"_"+keywords[0])));
			}else{
				maps.put(keywords[0], sequenceManager.getNextSequence(Tablename+"_"+keywords[0]));
			}
			t = ModelUtil.put(t, maps);
			return maps.get(keywords[0]);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 获取主键值
	 * @param key
	 * @param t
	 * @return
	 */
	private Object getObjKey(Method key,T t) {
		try {
			return  key.invoke(t);
		} catch (Exception e) {
			log.error(e);
		}
		return null;
	}
	
	public void modify(IMyDb db,T t) throws SQLException, ManagerException, WKDbException   {
		log.debug("modify "+t.getClass().getName());
		dbFactory.update(db, t,keywords);
		log.debug("save bgryxxb finish");
	}
	
	public void delete(IMyDb db,T t) throws SQLException, ManagerException, WKDbException  {
		dbFactory.delobj(db, t,keywords);
	}

	public PageModel<T> findAll(IMyDb db,int pageNo,int pageSize)  throws SQLException, WKDbException {
		SQLUtil sql = new SQLUtil();
		sql.setSQL("from "+Tablename+" WHERE 1=1 ");
		Boolean[] oders = new Boolean[keywords.length];
		for (int i = 0; i < oders.length; i++) {
			oders[i] = Boolean.TRUE;
			
		}
		return dbFactory.get_cutpage(db, getModuleClass(), "", sql, pageSize, pageNo, keywords, oders);
	}
	
	public List<T> findAll(IMyDb db) throws SQLException, WKDbException {
		String orderbystr="";
		for (int i = 0; i < keywords.length; i++) {
			if(i>0) orderbystr += ", ";
			orderbystr +=  keywords[i];
		}
		SQLUtil sql = new SQLUtil();
		sql.setSQL("SELECT * from "+Tablename+" WHERE 1=1 ");
		sql.setSQL("order by "+orderbystr);
		return dbFactory.query(db, getModuleClass(), sql);
	}

	public T findById(IMyDb db,Object... key)  throws SQLException, WKDbException {
		if(key==null) return null;
		String sql = "SELECT * from "+Tablename+" where ";
		for (int i = 0; i < keywords.length; i++) {
			if(i>0) sql += " AND ";
			sql +=  keywords[i]+"=?";
		}
		return dbFactory.getOne(db, sql,getModuleClass(), key);
	}
	
	public static void main(String[] args) {
	}
}
